/** 
 * \file gdcopy.cu
 * \author Kyle E. Niemeyer
 * \date 10/04/2011
 *
 * Based on "dcopy.f" from BLAS.
 *
 */

////////////////////////////////////////////////////////////////////////

/** gdcopy copies a double precision vector into another. BLAS level one.
 * uses unrolled loops for increments equal to one.
 *
 * \param[in]   n       number of elements in vector
 * \param[in]   dx      vector to be copied
 * \param[in]   incx    increment between elements of dx
 * \param[out]  dy      result vector, dimension (n-1) * |incy| + 1
 * \param[in]   incy    increment between elements of dy
 */
__device__ __inline__ void gdcopy ( int n, const double *dx, int incx, double *dy, int incy )
{
  
  if ( n <= 0 ) return;
  
  if ( ( incx == 1 ) && ( incy == 1 ) ) {
    
    // both increments equal to 1
    
    // clean-up loop
    
    uint m = n % 7;
    if ( m != 0 ) {
      
      for ( uint i = 0; i < m; ++i ) {
        dy[i] = dx[i];
      }
      
      if ( n < 7 ) return;
    }
    
    for ( uint i = m; i < n; i += 7 ) {
      dy[i] = dx[i];
      dy[i + 1] = dx[i + 1];
      dy[i + 2] = dx[i + 2];
      dy[i + 3] = dx[i + 3];
      dy[i + 4] = dx[i + 4];
      dy[i + 5] = dx[i + 5];
      dy[i + 6] = dx[i + 6];
    }
    
  } else {
    
    // unequal increments or increments not equal to 1
    
    uint ix = 1;
    uint iy = 1;
    if ( incx < 0 ) ix = (-n + 1) * incx + 1;
    if ( incy < 0 ) iy = (-n + 1) * incy + 1;
    
    for ( uint i = 0; i < n; ++i ) {
      dy[iy] = dx[ix];
      ix += incx;
      iy += incy;
    }
    
  } // end increment if

} // end gdcopy